home *** CD-ROM | disk | FTP | other *** search
/ Aminet 22 / Aminet 22 (1997)(GTI - Schatztruhe)[!][Dec 1997].iso / Aminet / util / misc / cookietool.lha / cookietool / cdbsplit.c < prev    next >
C/C++ Source or Header  |  1997-10-25  |  11KB  |  351 lines

  1. /*========================================================================*\
  2.  |  File: cdbsplit.c                                   Date: 25 Oct 1997  |
  3.  *------------------------------------------------------------------------*
  4.  |    Split parts off your cookie database, by keyword, by line length,   |
  5.  |       by number of lines, or as groups of "similar" cookies.           |
  6.  | Expected file format is plain text with a "%%" line ending each cookie.|
  7.  |                     See help() for usage notes.                        |
  8.  |                                                                        |
  9. \*========================================================================*/
  10.    
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <ctype.h>
  15. #include "strstuff.h"
  16.  
  17. char version[] = "$VER: cdbsplit 2.2 (25.10.97)";
  18.  
  19. #define FBUFSIZE 16384          /* we'll use larger file buffers */
  20. #define CBUFSIZE 32000L
  21. #define LBUFSIZE 2000
  22. #define NTARGET 10              /* max. number of keywords to search for */
  23. char line[LBUFSIZE];            /* large enough to hold the longest line */
  24. char cbuf[CBUFSIZE];            /* large enough to hold one complete cookie */
  25. char cbak[CBUFSIZE];            /* backup of the last cookie, to find groups */
  26. char uppercase[256];            /* conversion table */
  27.  
  28. int l_min = 1, l_max = 0, w_min = 1, w_max = 0;
  29. long n_min = 1, n_max = 0;
  30. int matchlen = 0;
  31. char *rtarget[NTARGET];         /* required keywords */
  32. char *otarget[NTARGET];         /* optional keywords */
  33. int required = 0, optional = 0;
  34.  
  35.  
  36. /* 
  37.  * print a help text and nag about illegal parameter <s> 
  38.  */
  39. void help( char *s )
  40. {
  41.   if( s )
  42.     printf( "illegal option '%s'\n", s );
  43.   printf( "usage:  cdbsplit [options] <cookiefile> <newfile>\n" );
  44.   printf( "where options are:\n" );
  45.   printf( " -k<keywd> / -K<keywd>  search for optional / required keyword\n" );
  46.   printf( " -l<lines> / -L<lines>  range for number of lines in a cookie\n" );
  47.   printf( " -w<width> / -W<width>  range for cookie line width\n" );
  48.   printf( " -n<no.>   / -N<no.>    range of cookie numbers\n" );
  49.   printf( " -m<m>     extract groups of cookies with <m> matching chars\n" );
  50.   printf( " -d[0-3]   how fussy about word delimiters? (default: 2) \n" );
  51.   printf( " -c        case sensitive comparisons\n" );
  52.   printf( " -x        extract only, do not modify the input file\n" );
  53.   printf( " -a        append to an existing output file\n" );
  54. }
  55.  
  56.  
  57.  
  58. int dispatch( char *cookie, int good, FILE *fp2, FILE *fp3 )
  59. {
  60.   long result = 1;
  61.   
  62.   if( good )
  63.     result = fprintf( fp2, "%s%%%%\n", cookie );
  64.   else if( fp3 )
  65.     result = fprintf( fp3, "%s%%%%\n", cookie );
  66.   if( result <= 0 )
  67.     {
  68.       printf( "\nfile error, aborted !!!\n" );
  69.       exit( 20 );
  70.     }
  71.   return good ? 1 : 0;
  72. }
  73.  
  74.  
  75. long filter_cookies( FILE *fp1, FILE *fp2, FILE *fp3 )
  76. /* scatter contents of <fp1> across <fp2> (hitfile) and <fp3> (dumpfile),
  77.  * return value is the number of cookies in the dumpfile
  78.  */
  79. {
  80.   long count = 0, hits = 0, cbuflen;
  81.   int ok = 0, ok2, lines, width, w, i;
  82.  
  83.   strcpy( cbak, "" );
  84.   strcpy( cbuf, "" );
  85.   cbuflen = lines = width = 0;
  86.   while( fgets( line, LBUFSIZE, fp1 ) )
  87.     {
  88.       if( strncmp( line, "%%", 2 ) == 0 )
  89.         {                       /* "end of cookie"-marker */
  90.           count++;
  91.           /* perform the checks: */
  92.           if( matchlen )        /* "similar cookies" mode */
  93.             {
  94.               ok2 = ok;
  95.               ok = (strn_cmp( cbak, cbuf, matchlen ) == 0);
  96.               if( *cbak )       /* skip the first loop */
  97.                 hits += dispatch( cbak, ok || ok2, fp2, fp3 );
  98.               strcpy( cbak, cbuf );
  99.             }
  100.           else                  /* standard mode */
  101.             {
  102.               ok = (lines >= l_min && width >= w_min && count >= n_min);
  103.               if( l_max )
  104.                 ok = ok && ( lines <= l_max );
  105.               if( w_max )
  106.                 ok = ok && ( width <= w_max );
  107.               if( n_max )
  108.                 ok = ok && ( count <= n_max );
  109.               if( ok )          /* string checks still necessary? */
  110.                 {
  111.                   if( required == 0 && optional > 0 )
  112.                     ok = 0;
  113.                   for( i = 0; i < required; i++ )
  114.                     ok = ok && (str_str( cbuf, rtarget[i] ) != NULL);
  115.                   for( i = 0; i < optional; i++ )
  116.                     ok = ok || (str_str( cbuf, otarget[i] ) != NULL);
  117.                 }
  118.               hits += dispatch( cbuf, ok, fp2, fp3 );
  119.             }
  120.           if( count % 100 == 0 )
  121.             {
  122.               printf( "%ld hits/%ld misses.\r", hits, count - hits );
  123.               fflush( stdout );
  124.             }
  125.           strcpy( cbuf, "" );   /* start a new cookie */
  126.           cbuflen = lines = width = 0;
  127.         }
  128.       else                      /* add a line to the current cookie */
  129.         {
  130.           w = strlen( line );
  131.           if( (cbuflen += w) >= CBUFSIZE )
  132.             {
  133.               printf( "\ncookie too big (>%ld chars) \n", CBUFSIZE );
  134.               exit( 20 );
  135.             }
  136.           strcat( cbuf, line );
  137.           lines++;
  138.           if( w > width )
  139.             width = w;
  140.         }
  141.     }
  142.   if( matchlen )                /* one cookie still pending in this mode */
  143.     hits += dispatch( cbak, ok, fp2, fp3 );
  144.   printf( "Done, %ld hits out of %ld\n", hits, count );
  145.   return (count - hits);
  146. }
  147.  
  148.  
  149.  
  150. void confirm_options()
  151. /* tell the user what his options will do */
  152.   int flags, i;
  153.   
  154.   if( matchlen )
  155.     printf( "  searching for groups of cookies with "
  156.             "%d matching characters.\n", matchlen );
  157.   else
  158.     {
  159.       flags = 0xf;              /* what restrictions do apply? */
  160.       if( optional + required > 0 )
  161.         {
  162.           printf( "  search string%s: ", (optional + required > 1) ? "s" : "");
  163.           if( required > 1 && optional > 0 )
  164.             printf("(");
  165.           if( required > 0 )
  166.             {            
  167.               printf( "\"%s\"", rtarget[0] );
  168.               for( i = 1; i < required; i++ )
  169.                 printf( " && \"%s\"", rtarget[i] );
  170.             }
  171.           if( required > 1 && optional > 0 )
  172.             printf(")");
  173.           if( required > 0 && optional > 0 )
  174.             printf(" || ");
  175.           if( optional > 0 )
  176.             {
  177.               printf( "\"%s\"", otarget[0] );
  178.               for( i = 1; i < optional; i++ )
  179.                 printf( " || \"%s\"", otarget[i] );
  180.             }
  181.           printf( "\n" ); 
  182.         }
  183.       else
  184.         flags ^= 1;
  185.       if( l_max )
  186.         printf( "  looking for cookies %d - %d lines long.\n", l_min, l_max );
  187.       else if( l_min > 1 )
  188.         printf( "  looking for cookies at least %d lines long.\n", l_min );
  189.       else
  190.         flags ^= 2;
  191.       if( w_max )
  192.         printf( "  looking for cookies %d - %d columns wide.\n", w_min, w_max );
  193.       else if( w_min > 1 )
  194.         printf( "  looking for cookies at least %d columns wide.\n", w_min );
  195.       else
  196.         flags ^= 4;
  197.       if( n_max )
  198.         printf( "  considering cookies #%ld - #%ld only.\n", n_min, n_max);
  199.       else if( n_min > 1 )
  200.         printf( "  starting at cookie #%ld.\n", n_min );
  201.       else
  202.         flags ^= 8;
  203.       if( flags == 0 )
  204.         printf( "  no restrictions.\n" );
  205.     }
  206. }
  207.  
  208.  
  209. int main( int argc, char *argv[] )
  210. {
  211.   char *s;
  212.   char *name1 = NULL, *name2 = NULL, *name3 = "cdb_temp_kickme";
  213.   int append = 0, move = 1;
  214.   int case_sense = 0, bordermode = 2;
  215.   long dumped;
  216.   FILE *infile, *hitfile, *dumpfile;
  217.  
  218.   if( argc < 3 )
  219.     {
  220.       help( NULL );
  221.       return 5;
  222.     }
  223.   while( --argc )
  224.     {
  225.       s = *++argv;
  226.       if( *s != '-' )
  227.         {
  228.           if( name1 == NULL )
  229.             name1 = s;
  230.           else       
  231.             name2 = s;
  232.         }
  233.       else
  234.         {
  235.           s++;
  236.           switch( *s++ )
  237.             {
  238.             case 'k':
  239.               if( optional < NTARGET )
  240.                 otarget[ optional++ ] = s;
  241.               break;
  242.             case 'K':
  243.               if( required < NTARGET )
  244.                 rtarget[ required++ ] = s;
  245.               break;
  246.             case 'm':
  247.               matchlen = atoi( s );
  248.               break;
  249.             case 'l':
  250.               l_min = atoi( s );
  251.               break;
  252.             case 'L':
  253.               l_max = atoi( s );
  254.               break;
  255.             case 'w':
  256.               w_min = atoi( s );
  257.               break;
  258.             case 'W':
  259.               w_max = atoi( s );
  260.               break;
  261.             case 'n':
  262.               n_min = atol( s );
  263.               break;
  264.             case 'N':
  265.               n_max = atol( s );
  266.               break;
  267.             case 'a':
  268.               append = 1;
  269.               break;
  270.             case 'x':
  271.               move = 0;
  272.               break;
  273.             case 'c':
  274.               case_sense = 1;
  275.               break;
  276.             case 'd':
  277.               if( isdigit( *++s ) )
  278.                 bordermode = atoi( s );
  279.               else
  280.                 {
  281.                   help( argv[0] );
  282.                   return 5;
  283.                 }
  284.               break;
  285.             default:
  286.               help( argv[0] );
  287.               return 5;
  288.             }
  289.         }
  290.     }
  291.   str_setup( bordermode, case_sense ); /* !!! */
  292.   if( name1 == NULL || name2 == NULL )
  293.     {
  294.       help( NULL );
  295.       return 5;
  296.     }
  297.   if( !(infile = fopen( name1, "r" ) ) )
  298.     {
  299.       printf( "Can't open '%s' for input!\n", name1 );
  300.       return 10;
  301.     }
  302.   setvbuf( infile, NULL, _IOFBF, FBUFSIZE );
  303.   if( !append && (hitfile = fopen( name2, "r" )) )
  304.     {
  305.       printf( "Error: '%s' exists!  Use -a to append.\n", name2 );
  306.       return 10;
  307.     }
  308.   if( !(hitfile = fopen( name2, "a" )) )
  309.     {
  310.       printf( "Can't open '%s' for output!\n", name2 );
  311.       return 10;
  312.     }
  313.   setvbuf( hitfile, NULL, _IOFBF, FBUFSIZE );
  314.   if( move )
  315.     {
  316.       if( !(dumpfile = fopen( name3, "w" ) ) )
  317.         {
  318.           printf( "Can't open '%s' for output!\n", name3 );
  319.           return 10;
  320.         }
  321.       setvbuf( dumpfile, NULL, _IOFBF, FBUFSIZE );
  322.     }
  323.   else
  324.     dumpfile = NULL;
  325.   printf( "CdbSplit " );           
  326.   print_strstat();
  327.   printf( "%sing from '%s' to '%s',\n", move ? "Mov" : "Copy", name1, name2 );
  328.   confirm_options();            
  329.   /* OK, here we go: */
  330.   dumped = filter_cookies( infile, hitfile, dumpfile );
  331.   fclose( infile );
  332.   fclose( hitfile );
  333.   if( move )
  334.     {
  335.       fclose( dumpfile );
  336.       if( remove( name1 ) != 0 || rename( name3, name1 ) != 0 )
  337.         {
  338.           printf( "Couldn't overwrite the input file!  Your cookies are in '%s'.\n", name3 );
  339.           return 5;
  340.         }
  341.       if( dumped == 0 )
  342.         {
  343.           remove( name1 );
  344.           printf( "'%s' is now empty and has been deleted.\n", name1 );
  345.         }
  346.     }
  347.   return 0;
  348. }
  349.  
  350.